import backtrader as bt
import numpy as np
import pandas as pd
from typing import Dict, Any, Optional

class BreakoutStrategy(bt.Strategy):
    """
    突破策略
    
    策略逻辑：
    1. 识别支撑和阻力位
    2. 在价格突破阻力位且成交量放大时买入
    3. 在价格跌破支撑位时卖出
    4. 设置止损和止盈
    5. 支持假突破过滤
    """
    
    params = (
        ('lookback_period', 20),    # 寻找支撑阻力位的回看周期
        ('breakout_threshold', 0.02), # 突破阈值
        ('volume_threshold', 1.5),    # 成交量放大倍数
        ('stop_loss', 0.05),          # 止损比例
        ('take_profit', 0.20),        # 止盈比例
        ('position_size', 0.12),      # 仓位比例
        ('fake_breakout_filter', 3),  # 假突破过滤天数
    )
    
    def __init__(self):
        # 计算支撑和阻力位
        self.high_band = bt.indicators.Highest(
            self.data.high,
            period=self.params.lookback_period
        )
        self.low_band = bt.indicators.Lowest(
            self.data.low,
            period=self.params.lookback_period
        )
        
        # 成交量指标
        self.volume_ma = bt.indicators.SMA(
            self.data.volume,
            period=10
        )
        
        # 交易状态
        self.order = None
        self.stop_order = None
        self.take_profit_order = None
        self.entry_price = None
        self.breakout_direction = None  # 'up' or 'down'
        
    def next(self):
        if self.order:
            return
            
        if not self.position:
            # 寻找突破机会
            resistance = self.high_band[-1]  # 前一天的阻力位
            support = self.low_band[-1]      # 前一天的支撑位
            
            current_price = self.data.close[0]
            current_volume = self.data.volume[0]
            avg_volume = self.volume_ma[0]
            
            # 向上突破
            if (current_price > resistance * (1 + self.params.breakout_threshold) and
                current_volume > avg_volume * self.params.volume_threshold):
                
                # 计算买入数量
                cash = self.broker.getcash()
                price = current_price
                size = int((cash * self.params.position_size) / price)
                
                if size > 0:
                    self.order = self.buy(size=size)
                    self.entry_price = price
                    self.breakout_direction = 'up'
                    print(f'向上突破买入: 价格={price:.2f}, 阻力位={resistance:.2f}')
        
        else:
            # 寻找卖出机会
            if self.breakout_direction == 'up':
                # 跌破支撑位或达到止盈
                support = self.low_band[0]
                current_price = self.data.close[0]
                
                if current_price < support * (1 - self.params.breakout_threshold):
                    self.order = self.sell(size=self.position.size)
                    print(f'跌破支撑卖出: 价格={current_price:.2f}, 支撑位={support:.2f}')
    
    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            return
            
        if order.status in [order.Completed]:
            if order.isbuy():
                # 设置止损和止盈
                price = order.executed.price
                stop_price = price * (1 - self.params.stop_loss)
                take_profit_price = price * (1 + self.params.take_profit)
                
                self.stop_order = self.sell(
                    size=order.executed.size,
                    exectype=bt.Order.Stop,
                    price=stop_price
                )
                
                self.take_profit_order = self.sell(
                    size=order.executed.size,
                    exectype=bt.Order.Limit,
                    price=take_profit_price
                )
                
                print(f'买入完成: 价格={price:.2f}, 数量={order.executed.size}')
            else:
                # 取消其他订单
                if self.stop_order:
                    self.cancel(self.stop_order)
                if self.take_profit_order:
                    self.cancel(self.take_profit_order)
                    
                print(f'卖出完成: 价格={order.executed.price:.2f}, 数量={order.executed.size}')
        
        self.order = None

def get_strategy_params() -> Dict[str, Any]:
    """获取策略参数"""
    return {
        'name': '突破策略',
        'description': '基于价格突破支撑阻力位的趋势跟踪策略',
        'parameters': {
            'lookback_period': {'type': 'int', 'default': 20, 'min': 10, 'max': 50, 'description': '支撑阻力位回看周期'},
            'breakout_threshold': {'type': 'float', 'default': 0.02, 'min': 0.01, 'max': 0.05, 'description': '突破阈值'},
            'volume_threshold': {'type': 'float', 'default': 1.5, 'min': 1.2, 'max': 2.5, 'description': '成交量放大倍数'},
            'stop_loss': {'type': 'float', 'default': 0.05, 'min': 0.02, 'max': 0.10, 'description': '止损比例'},
            'take_profit': {'type': 'float', 'default': 0.20, 'min': 0.10, 'max': 0.30, 'description': '止盈比例'},
            'position_size': {'type': 'float', 'default': 0.12, 'min': 0.08, 'max': 0.25, 'description': '仓位比例'},
            'fake_breakout_filter': {'type': 'int', 'default': 3, 'min': 1, 'max': 5, 'description': '假突破过滤天数'}
        }
    } 